#pragma once
#include <functional>
#include <iostream>
#include <pthread.h>
using namespace std;
namespace ThreadModule {
    static uint32_t number = 1;
    template<class T>
    class Thread {
        using func_t = function<void(T)>;
        private:
            void EnableRunning() {
                is_running = true;
            }
            static void* routine(void* args) {
                Thread<T>* self = static_cast<Thread<T>*>(args);
                self->EnableRunning();
                if(self->is_detach) {
                    self->Detach();
                }
                // pthread_setname_np(self->tid, self->name.c_str());
                self->func(self->data);
                return nullptr;
            }
        public:
            Thread(func_t f, T d) :
            tid(0), 
            is_detach(false),
            is_running(false),
            res(nullptr),
            func(f),
            data(d) {
                name = "thread-" + to_string(number++);
            }
            void Detach() {
                if(is_detach) {
                    return;
                }
                if(is_running) {
                    pthread_detach(tid);
                }
                cout << "线程已经分离了！" << endl;
                is_detach = true;
            }
            bool Start() {
                if(is_running) {
                    return false;
                }
                int n = pthread_create(&tid, nullptr, routine, this);
                if(n != 0) {
                    cerr << "create pthread error！" << endl;
                    return false;
                }else {
                    cout << "create pthread success, name is " << name << endl;
                    return true;
                }
            }
            bool Stop() {
                if(is_running) {
                    int n = pthread_cancel(tid);
                    if(n != 0) {
                        cerr << "cancel pthread error！" << endl;
                        return false;
                    }else {
                        cout << name << " stop" << endl;
                        is_running = false;
                        return true;
                    }
                }else {
                    return false;
                }
            }
            void Join() {
                if(is_detach) {
                    cout << "已经分离了!" << endl;
                    return;
                }
                int n = pthread_join(tid, &res);
                if(n != 0) {
                    cerr << "detach pthread error！" << endl;
                    return;
                }else {
                    cout << "detach success！" << endl;
                }
            }
            ~Thread() {

            }
        private:
            pthread_t tid;
            string name;
            bool is_detach;
            bool is_running;
            void* res;
            func_t func;
            T data;
    };
}